package com.qiaofang.applet.rest;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.qiaofang.applet.common.context.QfContextHolder;
import com.qiaofang.applet.common.dto.DataRequest;
import com.qiaofang.applet.common.dto.DataResponse;
import com.qiaofang.applet.common.exception.BusinessException;
import com.qiaofang.applet.constants.SearchTypeConstants;
import com.qiaofang.applet.constants.UpDownFlagConstants;
import com.qiaofang.applet.constants.switchConfigConstants;
import com.qiaofang.applet.service.member.domain.Employee;
import com.qiaofang.applet.service.member.service.EmployeeService;
import com.qiaofang.applet.service.member.service.dto.EmployeeAtoolQueryDto;
import com.qiaofang.applet.service.other.domain.Corporation;
import com.qiaofang.applet.service.other.domain.EmployeeLabel;
import com.qiaofang.applet.service.other.service.*;
import com.qiaofang.applet.service.other.service.dto.*;
import com.qiaofang.applet.service.property.domain.*;
import com.qiaofang.applet.service.property.service.*;
import com.qiaofang.applet.service.property.service.dto.*;
import com.qiaofang.applet.service.property.service.mapstruct.AreaMapper;
import com.qiaofang.applet.service.property.service.mapstruct.DistrictMapper;
import com.qiaofang.applet.service.property.service.mapstruct.EstateMapper;
import com.qiaofang.applet.service.property.service.mapstruct.FirsthandEstateMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/web/common")
@Api(tags = "公共：公共接口")
public class CommonController {

    @Autowired
    CityCompanyService cityCompanyService;

    @Autowired
    DistrictService districtService;

    @Autowired
    AreaService areaService;

    @Autowired
    AreaMapper areaMapper;

    @Autowired
    DistrictMapper districtMapper;

    @Autowired
    FirsthandEstateMapper firsthandEstateMapper;

    @Autowired
    DictCorpService dictCorpService;

    @Autowired
    EstateService estateService;

    @Autowired
    ProvinceCityService provinceCityService;

    @Autowired
    PropertyService propertyService;

    @Autowired
    FirsthandEstateService firsthandEstateService;

    @Autowired
    EstateMapper estateMapper;

    @Autowired
    WxaQrCodeService wxaQrCodeService;

    @Autowired
    private WxaUnlimitQrCodeService wxaUnlimitQrCodeService;

    @Autowired
    private ShortCodeService shortCodeService;

    @Autowired
    private CorporationService corporationService;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    EmployeeLabelService employeeLabelService;

    @Value("${atool.url}")
    private String url;

    @Value("${atool.appId}")
    private String appId;

    @Value("${atool.appKey}")
    private String appKey;

    @PostMapping("/getCityList")
    @ApiOperation(value = "城市列表", notes = "城市列表")
    public DataResponse<List<CityDesDto>> getCityList() {
        return DataResponse.ok(cityCompanyService.getCityList(QfContextHolder.getContext().getCorporationCode()));
    }

    @PostMapping("/getDistrictList")
    @ApiOperation(value = "区域列表", notes = "区域列表")
    public DataResponse<List<DistrictDto>> getDistrictList(@RequestBody @Valid DataRequest<CityQueryDto> request) {
        List<District> districtList = districtService.findAllByCityCode(request.getParam().getCityCode());

        return DataResponse.ok(districtList.parallelStream().map(districtMapper::domainToDto).collect(Collectors.toList()));
    }

    @PostMapping("/getAreaList")
    @ApiOperation(value = "商圈列表", notes = "商圈列表")
    public DataResponse<List<AreaDto>> getAreaList(@RequestBody @Valid DataRequest<UuidDto> request) {
        List<Area> areaList = areaService.findAllByDistrictUuid(request.getParam().getUuid());

        return DataResponse.ok(areaList.parallelStream().map(areaMapper::domainToDto).collect(Collectors.toList()));
    }

    @PostMapping("/getDistrictAndArea")
    @ApiOperation(value = "城区商圈列表", notes = "城区商圈列表")
    public DataResponse<List<DistrictAreaDto>> getDistrictAndArea(@RequestBody @Valid DataRequest<CityQueryDto> request) {
        List<DistrictAreaDto> list = districtService.findAllDistrictAndArea(QfContextHolder.getContext().getCorporationCode(), request.getParam().getCityCode());
        return DataResponse.ok(list);
    }

    @PostMapping("/getDictList")
    @ApiOperation(value = "字典列表接口", notes = "字典列表接口")
    public DataResponse<Map<String, List<DictDto>>> getDictList(@RequestBody DataRequest<DictTypeDto> request) {
        Map<String, List<DictDto>> result = dictCorpService.getDictCollectionByType(request.getParam().getDictTypeSet(), QfContextHolder.getContext().getCorporationCode());
        return DataResponse.ok(result);
    }

    @PostMapping("/mainSearch")
    @ApiOperation(value = "首页搜索", notes = "首页搜索")
    public DataResponse<List<MainSearchDetailDTO>> mainSearch(@RequestBody @Valid DataRequest<MainSearchQueryDTO> request) {
        List<MainSearchDetailDTO> result = new ArrayList<>();

        if (SearchTypeConstants.FIRSTHAND_ESTATE.getValue().equals(request.getParam().getSearchType())) {
            FirsthandEstateQueryDto firsthandEstateQueryDto = new FirsthandEstateQueryDto();
            firsthandEstateQueryDto.setEstateName(request.getParam().getSearchName());
            firsthandEstateQueryDto.setCityCode(request.getParam().getCityCode());
            firsthandEstateQueryDto.setUpDownFlag(UpDownFlagConstants.UP_FLAG.getValue());

            List<FirsthandEstate> firsthandEstateList = firsthandEstateService.findAllByParams(firsthandEstateQueryDto);

            result = Optional.ofNullable(firsthandEstateList).orElseGet(Lists::newArrayList).stream().map(item -> {
                MainSearchDetailDTO dto = new MainSearchDetailDTO();
                dto.setEstateName(item.getEstateName());
                dto.setCityName(item.getCityName());
                dto.setAreaName(item.getAreaName());
                dto.setPropertyTypeList(firsthandEstateMapper.splitString(item.getPropertyType()));
                dto.setEstateUniqueUuid(item.getEstateUniqueUuid());
                return dto;
            }).collect(Collectors.toList());

        } else if (SearchTypeConstants.SALE_PROPERTY.getValue().equals(request.getParam().getSearchType())) {
            SalePropertyQueryDto salePropertyQueryDto = new SalePropertyQueryDto();
            salePropertyQueryDto.setEstateName(request.getParam().getSearchName());
            salePropertyQueryDto.setCityCode(request.getParam().getCityCode());
            salePropertyQueryDto.setUpDownFlag(UpDownFlagConstants.UP_FLAG.getValue());
            //这个头部搜索数量同列表
            salePropertyQueryDto.setValidStatus(true);

            List<Property> salePropertyList = propertyService.findAllSaleByParams(salePropertyQueryDto);
            Map<String, List<Property>> estateMap = Optional.ofNullable(salePropertyList)
                    .orElseGet(Lists::newArrayList).stream().filter(item -> StringUtils.isNotBlank(item.getEstateUniqueUuid()))
                    .collect(Collectors.groupingBy(Property::getEstateUniqueUuid));

            if (estateMap != null) {
                for (String estateUniqueUuid : estateMap.keySet()) {
                    List<Property> propertyList = estateMap.get(estateUniqueUuid);
                    MainSearchDetailDTO dto = estateMapper.domainToDtailDto(propertyList.get(0));
                    dto.setSaleNum(propertyList.size());
                    result.add(dto);
                }
            }
        } else if (SearchTypeConstants.RENT_PROPERTY.getValue().equals(request.getParam().getSearchType())) {
            RentPropertyQueryDto rentPropertyQueryDto = new RentPropertyQueryDto();
            rentPropertyQueryDto.setEstateName(request.getParam().getSearchName());
            rentPropertyQueryDto.setCityCode(request.getParam().getCityCode());
            rentPropertyQueryDto.setUpDownFlag(UpDownFlagConstants.UP_FLAG.getValue());
            rentPropertyQueryDto.setValidStatus(true);

            List<Property> rentPropertyList = propertyService.findAllRentByParams(rentPropertyQueryDto);

            Map<String, List<Property>> estateMap = Optional.ofNullable(rentPropertyList)
                    .orElseGet(Lists::newArrayList).stream().filter(item -> StringUtils.isNotBlank(item.getEstateUniqueUuid()))
                    .collect(Collectors.groupingBy(Property::getEstateUniqueUuid));

            if (estateMap != null) {
                for (String estateUniqueUuid : estateMap.keySet()) {
                    List<Property> propertyList = estateMap.get(estateUniqueUuid);
                    MainSearchDetailDTO dto = estateMapper.domainToDtailDto(propertyList.get(0));
                    dto.setRentNum(propertyList.size());
                    result.add(dto);
                }
            }
        } else if (SearchTypeConstants.ESTATE.getValue().equals(request.getParam().getSearchType())) {
            EstateQueryDto estateQueryDto = new EstateQueryDto();
            estateQueryDto.setEstateName(request.getParam().getSearchName());
            estateQueryDto.setCityCode(StringUtils.defaultString(request.getParam().getCityCode(), QfContextHolder.getContext().getCityCode()));
            List<Estate> allEstateByParams = estateService.findAllEstateByParams(estateQueryDto);
            List<EstateListDto> estateListDtos = estateService.convertDomainToEstateListDto(allEstateByParams);
            result = Optional.ofNullable(estateListDtos).orElseGet(Lists::newArrayList).stream().map(item -> {
                MainSearchDetailDTO mainSearchDetailDTO = new MainSearchDetailDTO();
                mainSearchDetailDTO.setOldEstateUniqueUuid(item.getEstateUniqueUuid());
                mainSearchDetailDTO.setEstateName(item.getEstateName());
                mainSearchDetailDTO.setRentNum(item.getRentNum());
                mainSearchDetailDTO.setSaleNum(item.getSaleNum());
                return mainSearchDetailDTO;
            }).collect(Collectors.toList());
        }
        return DataResponse.ok(result);
    }


    @PostMapping("/getFirstCityList")
    @ApiOperation(value = "新房城市列表", notes = "新房城市列表")
    public DataResponse<List<CityDesDto>> getFirstCityList() {
        List<CityDesDto> firstHandCityAndArea = provinceCityService.getFirstHandCity(QfContextHolder.getContext().getCorporationCode());
        return DataResponse.ok(firstHandCityAndArea);
    }

    @PostMapping("/getFirstAreaList")
    @ApiOperation(value = "新房城市区域列表", notes = "新房城市区域列表")
    public DataResponse<List<DistrictDto>> getFirstAreaList(@RequestBody @Valid DataRequest<CityQueryDto> request) {
        if (StringUtils.isBlank(request.getParam().getCityCode())) {
            throw new BusinessException("请先选择城市");
        }
        List<DistrictDto> firstHandArea = provinceCityService.getFirstHandArea(request.getParam().getCityCode());
        return DataResponse.ok(firstHandArea);
    }

    @PostMapping("/getWxQRCode")
    @ApiOperation(value = "获取微信小程序码", notes = "获取微信小程序码")
    public DataResponse<String> getWxQRCode(@RequestBody DataRequest<WxaQrCodeDto> request) {
        log.info("getWxQRCode params: {}", JSONObject.toJSONString(request));
        String qrCode = wxaQrCodeService.createQrCode(request.getParam());
        return DataResponse.ok(qrCode);
    }

    @PostMapping("/getUnlimitWxQRCode")
    @ApiOperation(value = "获取微信小程序码（不限次数）", notes = "获取微信小程序码（不限次数）")
    public DataResponse<String> getUnlimitWxQRCode(@RequestBody DataRequest<WxaUnlimitQrCodeDto> request) {
        return DataResponse.ok(wxaUnlimitQrCodeService.createMiniQrCode(request.getParam()));
    }

    @Deprecated
    @PostMapping("/getShortCode")
    @ApiOperation(value = "获取短码", notes = "获取短码")
    public DataResponse<List<String>> getShortCode(@RequestBody DataRequest<List<GetCodeDto>> request) {
        return DataResponse.ok(shortCodeService.getShortCodeList(request.getParam()));
    }

    @Deprecated
    @PostMapping("/getUniqueUuid")
    @ApiOperation(value = "获取唯一uuid", notes = "获取唯一uuid")
    public DataResponse<List<String>> getUniqueUuid(@RequestBody DataRequest<List<GetUniqueUuidDto>> request) {
        return DataResponse.ok(shortCodeService.getUniqueUuidList(request.getParam()));
    }

    @PostMapping("/getOtherLogo")
    @ApiOperation(value = "获取关注logo图标", notes = "获取关注logo图标")
    public DataResponse<List<DictDto>> getOtherLogo() {
        return DataResponse.ok(dictCorpService.getOtherLogo(QfContextHolder.getContext().getCorporationCode()));
    }

    @PostMapping("/getPrivacyAgreement")
    @ApiOperation(value = "获取集团隐私协议", notes = "获取集团隐私协议")
    public DataResponse<String> getPrivacyAgreement() {
        Corporation corporation = corporationService.getCorporationByCorporationCode(QfContextHolder.getContext().getCorporationCode());
        if (corporation == null){
            throw new BusinessException("集团不存在");
        }
        return DataResponse.ok(corporation.getPrivacyAgreement());
    }

    @PostMapping("/getCityInformation")
    @ApiOperation(value = "获取单个城市消息", notes = "获取单个城市消息")
    public DataResponse<SingleCityDto> getCityInformation(@RequestBody @Valid DataRequest<CityQueryDto> cityQueryDto) {
        SingleCityDto singleCityDto = null;
        try {
            String corporationCode = QfContextHolder.getContext().getCorporationCode();
            singleCityDto = new SingleCityDto();
            List<CityDesDto> cityList = cityCompanyService.getCityList(corporationCode);
            for (CityDesDto cityDesDto : cityList) {
                if (StringUtils.equals(cityDesDto.getCityCode(), cityQueryDto.getParam().getCityCode())) {
                    singleCityDto.setCityName(cityDesDto.getCityName());
                    singleCityDto.setUniverseCityId(cityDesDto.getUniverseCityId());
                    break;
                }
            }
            String companyUuid = cityCompanyService.getCompanyUuid(cityQueryDto.getParam().getCityCode(), corporationCode);
            singleCityDto.setCompanyUuid(companyUuid);
            singleCityDto.setCityCode(cityQueryDto.getParam().getCityCode());
        } catch (Exception e) {
            log.error("获取单个城市数据异常：{}", e);
        }
        return DataResponse.ok(singleCityDto);
    }

    @PostMapping("/getCommerceAcademyConfig")
    @ApiOperation(value = "获取商学院跳转信息", notes = "获取商学院跳转信息")
    public DataResponse<CommerceAcademyDto> getCommerceAcademyConfig() {
        return DataResponse.ok(corporationService.getCommerceAcademyConfig());
    }

    @PostMapping("/getAutoEmployeeReply")
    @ApiOperation(value = "获取聊天自动回复内容", notes = "获取聊天自动回复内容")
    public DataResponse<String> getAutoEmployeeReply(@RequestBody DataRequest<AutoEmployeeReplyDto> request) {
        return DataResponse.ok(corporationService.getAutoEmployeeReply(request.getParam().getUniqueUuid(), request.getParam().getMemberId()));
    }

    @PostMapping("/getCorporationName")
    @ApiOperation(value = "获取集团名称", notes = "获取集团名称")
    public DataResponse<String> getCorporationName() {
        Corporation corporation = corporationService.getCorporationByCorporationCode(QfContextHolder.getContext().getCorporationCode());
        if (corporation == null) {
            throw new BusinessException("该集团不存在！");
        }
        return DataResponse.ok(corporation.getCorporationName());
    }

    @PostMapping("/getMiniProgramPath")
    @ApiOperation(value = "获取巧客力小程序信息", notes = "获取巧客力小程序信息")
    public DataResponse<JSONObject> getMiniProgramPath(@RequestBody @Valid DataRequest<EmployeeAtoolQueryDto> request) {
        //获取开关
        String corporationCode = QfContextHolder.getContext().getCorporationCode();
        Corporation corporation = corporationService.getCorporationByCorporationCode(corporationCode);
        if (corporation == null || corporation.getSwitchConfig() == null) {
            throw new BusinessException("集团配置信息不存在");
        }
        //关闭
        if (corporation.getSwitchConfig().getChocolate().equals(switchConfigConstants.CLOSED.getValue())){
            log.info("corporation atool is closed:{}", corporationCode);
            return DataResponse.ok(null);
        }
        String companyUuid = cityCompanyService.getCompanyUuid(QfContextHolder.getContext().getCityCode(), corporationCode);
        Employee employee = employeeService.findByEmployeeUniqueUuid(request.getParam().getEmployeeUniqueUuid());
        if (employee == null) {
            throw new BusinessException("经纪人信息不存在");
        }

        Map<String, Object> params = new HashMap<>();
        params.put("externalCompanyUuid", companyUuid);
        params.put("externalEmployeeUuid", employee.getEmployeeUuid());
        params.put("pathType", "AT_2C_BIZ_CARD");
        params.put("sourceType", "GWXCX");
        JSONObject miniProgramPath = corporationService.getMiniProgramPath(params, url, appId, appKey);
        return DataResponse.ok(miniProgramPath);
    }

    @PostMapping("/getServerTemplateId")
    @ApiOperation(value = "获取微信服务通知模板", notes = "获取微信服务通知模板")
    public DataResponse<String> getServerTemplateId() {
        return DataResponse.ok(corporationService.getServerTemplateId());
    }

    @PostMapping("/getEmployeeLabelList")
    @ApiOperation(value = "获取经纪人标签列表(筛选条件用)", notes = "获取经纪人标签列表")
    public DataResponse<List<EmployeeLabel>> getEmployeeLabelList() {
        return DataResponse.ok(corporationService.getEmployeeLabelList(QfContextHolder.getContext().getCorporationCode()));
    }

    @PostMapping("/eatateListSearchByName")
    @ApiOperation(value = "v20小区列表搜索", notes = "v20小区列表搜索")
    public DataResponse<List<MainSearchDetailDTO>> eatateListSearchByName(@RequestBody @Valid DataRequest<MainSearchQueryDTO> request) {
        return DataResponse.ok(propertyService.eatateListSearchByName(request.getParam()));
    }

}

